#!/usr/bin/python
# _*_ coding: utf8 _*_
#Created: 2010. 6. 19.
'''
class Name:     CTideDataCopyFromWeb
methods:        GetTideFromWeb
                GetDataFromWebData
                StoreHeightDB
                GetDataCronJob

sample:         MainRun = CTideDataCopyFromWeb()
                MainRun.GetTideFromWeb('INCHEON', 2010, 4)  #지정된 곳, 지정된 날짜 하나만 가지고 오기
                MainRun.GetDataCronJob()                    #다음달 데이터 싹 긁어오기
'''

##GLOBALS
g_stUrl = "http://www.khoa.go.kr/info/tide/"  #가져올 주소
g_dbFileName = './db/tide.db'   #sqlite DB 파일의 위치

##IMPORTS
import urllib2
import re
import sqlite3

class CTideDataCopyFromWeb():
    pass
    m_stResultWeb = ""    #웹에서 긁어온 데이터 저장
    m_stLocation = ""
    m_stYear = ""
    m_stMonth = ""

    #웹 데이터 가져오는 메소드
    def GetTideFromWeb(self, a_stUrlLocation, a_inUrlYear, a_inUrlMonth): 
        global g_stUrl
        
        #멤버 변수로 저장
        self.m_stLocation = a_stUrlLocation
        self.m_stYear = a_inUrlYear
        #월의 숫자가 한자리면0을 붙여서 두자리로 만들어서 멤버 변수로 저장
        if a_inUrlMonth < 10:
            stUrlMonth = '0' + str(a_inUrlMonth)
        else:
            stUrlMonth = str(a_inUrlMonth)
        self.m_stMonth = stUrlMonth
        
        #URL 만들기
        stUrlLocation = g_stUrl + a_stUrlLocation + '/' + str(a_inUrlYear) + stUrlMonth + '.htm'
        
        # 웹 데이터 불러오기
        try:
            opener = urllib2.build_opener()
            opener.addheaders = [("User-agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)")]
            response = opener.open(stUrlLocation)
            stWebData = response.read().decode('cp949').replace('&nbsp;&nbsp;','')\
                                                       .replace('\r','')\
                                                       .replace('\n','')\
                                                       .replace('\t','')
            #멤버 변수로 리턴
            self.m_stResultWeb = stWebData
        #실패 하면 None 입력
        except:
            self.m_stResultWeb = None
            print 'Error in Getting DATA'
        
        #위 단계가 성공이면 다음단계 시작
        if not self.m_stResultWeb == None:
            self.GetDataFromWebData()
        return

    #가져온 데이터를 정규식으로 분리 하는 메소드
    def GetDataFromWebData(self): 
        from BeautifulSoup import BeautifulSoup
        #BS로 해당 태그 내용 추출
        soup = BeautifulSoup(self.m_stResultWeb)
        soupResult = soup('td')
        
        #태그 내용에서 정규식으로 숫자 추출
        rePattern_1 = re.compile(r'(\d{2})\s:\s(\d{2})..(-?\d{1,3})')
        rePattern_2 = re.compile(r'(\d{2}).(\d{1,2})')
        
        #날짜 증가
        inDay = 1 
        #데이터 쌍을 저장할 튜플 초기화
        tupTideHeight = []
        
        #리스트 하나를 스트링으로 전환
        for stList in soupResult:
            stStringList = str(stList)
            #정상적인 숫자가 다 있으면 시간, 높이 추출
            if len(stStringList) >= 28:
                reResult = rePattern_1.findall(stStringList)
                dataSet_1,dataSet_2,dataSet_3 = reResult[0]
                dataSet = (self.m_stYear, self.m_stMonth, inDay, dataSet_1, dataSet_2, dataSet_3)
                tupTideHeight.append(dataSet)
            #숫자가 다 없으면 음력 표시
            elif 27 >= len(stStringList) >= 26: 
                reResult = rePattern_2.findall(stStringList)
                inDay = inDay + 1
            #이것도 저것도 아니면 빈 날
            else:
                reResult = 'Nothing'
        
        #완성된 튜플을 가지고 다음단계 시작
        self.StoreHeightDB(tupTideHeight)

    #날짜와 시간, 물 높이의 데이터 튜플을 받아서 DB에 저장하는 과정
    def StoreHeightDB(self, a_tupTideHeight):
        global g_dbFileName
        
        #데이터를 db에 저장하는 과정
        try:
            con = sqlite3.connect(g_dbFileName)
            cur = con.cursor()
            #테이블 없으면 생성
            cur.execute("CREATE TABLE IF NOT EXISTS " \
                        + self.m_stLocation \
                        + "(YEAR Integer, Month Integer, Day Integer ,Hour Integer, Min Integer, Height Integer);")
            #중복 데이터 제거
            try:
                cur.execute("DELETE FROM " + self.m_stLocation +" WHERE Month = "+ self.m_stMonth +";")
            except:
                print 'DELETE Error'
            #테이블에 데이터 저장
            cur.executemany("INSERT INTO " \
                            + self.m_stLocation \
                            + " VALUES(?, ?, ?, ?, ?, ?);", \
                            a_tupTideHeight)
            con.commit()
            print "DB Store OK"
        #실패하면 끝냄
        except:
            print "Error in Storing Data"
            
    
    #지역 데이터 세트대로 모든 페이지를 다 긁어오는 메소드
    def GetDataCronJob(self):
        #가져올 지역 목록
        dsAreaSet = [\
                        ('BAENGNYEONGDO', u"백령도"),\
                        ('DAECHEONGDO', u"대청도"),\
                        ('SUNWIDO', u"순위도"),\
                        ('DAEYEONPYEONGDO', u"대연평도"),\
                        ('DEOKJEOKDO', u"덕적도"),\
                        ('OEPORI', u"외포리"),\
                        #('GANGHWADO(LARGE BRIGE)', u"강화대교"),\
                        ('INCHEON', u"인천"),\
                        ('ANSAN', u"안산(탄도)"),\
                        ('PYEONGTAEK', u"평택"),\
                        ('DAESAN', u"대산"),\
                        ('ANHEUNG', u"안흥"),\
                        ('BORYEONG', u"보령"),\
                        ('EOCHEONGDO', u"어청도"),\
                        ('WIDO', u"위도"),\
                        ('JANGHANG', u"장항"),\
                        ('GUNSAN_OUTERPORT', u"군산외항"),\
                        ('ANMADO', u"안마도"),\
                        ('YEONGGWANG', u"영광"),\
                        ('MOKPO', u"목포"),\
                        ('DAEHEUKSANDO', u"대흑산도"),\
                        ('SEOGEOCHADO', u"서거차도"),\
                        ('BYEOKPAJIN', u"벽파진"),\
                        ('JINDO', u"진도"),\
                        ('WANDO', u"완도"),\
                        ('CHUJADO', u"추자도"),\
                        ('JEJU', u"제주"),\
                        ('MOSEULPO', u"모슬포"),\
                        ('SEOGWIPO', u"서귀포"),\
                        ('SEONGSANPO', u"성산포"),\
                        ('GEOMUNDO', u"거문도"),\
                        ('NOKDONG', u"녹동"),\
                        ('GOHEUNG', u"고흥(발포)"),\
                        ('GWANGYANG', u"광양"),\
                        ('YEOSU', u"여수"),\
                        ('SAMCHEONPO', u"삼천포"),\
                        ('TONGYEONG', u"통영"),\
                        ('MASAN', u"마산"),\
                        ('JINHAE', u"진해"),\
                        ('GEOJEDO', u"거제도(구조라)"),\
                        ('GADEOKDO', u"가덕도"),\
                        ('BUSAN', u"부산"),\
                        ('ULSAN', u"울산"),\
                        ('POHANG', u"포항"),\
                        ('HUPO', u"후포"),\
                        ('MUKHO', u"묵호"),\
                        ('SOKCHO', u"속초"),\
                        ('WONSAN', u"원산"),\
                        ('ULLEUNGDO', u"울릉도"),\
                        ('IEODO', u"이어도")
                    ]
        
        #다음달 설정
        import time, datetime
        inMonth = datetime.date.today().month
        if inMonth == 12:
            inMonth = 1
        else:
            inMonth = inMonth + 1
        
        #모든 지역 리스트에 대하여 데이터 수집
        for stArea in dsAreaSet:
            stAreaURL, stAreaName =  stArea
            print stAreaURL
            self.GetTideFromWeb(stAreaURL, 2010, inMonth)
            time.sleep(1)
        
        return
        #GetDataCronJob 끝

        

def main():
    pass
    MainRun = CTideDataCopyFromWeb()
    MainRun.GetTideFromWeb('BORYEONG', 2010, 6)
    #MainRun.GetDataCronJob()
    
if __name__ == "__main__":
    main()
